package org.memesis.pandorasbook.ui;

import javax.swing.Action;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.JTextPane;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultEditorKit;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.Style;
import javax.swing.text.StyledDocument;
import javax.swing.text.html.HTML;

import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.HashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 *   A class to support common tasks wanted for Pandora Applet text panes
 *
 * @author utena
 */
public class PandoraTextPane extends JTextPane implements MouseListener {

	/**
	 *   Serializable I guess?
	 */
	private static final long serialVersionUID = 6705521758660932492L;
	
	private JPopupMenu popupMenu;
	private JMenuItem cutItem, copyItem, pasteItem;
	private HashMap<Object, Action> actions;
	private Pattern URLRexEx;
	
	public JPopupMenu getPopupMenu() {
		return popupMenu;
	}
	
	public Action getEditorActionByName(String name) {
		return actions.get(name);
	}
	
	protected void createPoupuMenu() {
		popupMenu = new JPopupMenu();
		
		cutItem = new JMenuItem("Cut");
		cutItem.addActionListener(getEditorActionByName(DefaultEditorKit.cutAction));
		popupMenu.add(cutItem);

		copyItem = new JMenuItem("Copy");
		copyItem.addActionListener(getEditorActionByName(DefaultEditorKit.copyAction));
		popupMenu.add(copyItem);
	
		pasteItem = new JMenuItem("Paste");
		pasteItem.addActionListener(getEditorActionByName(DefaultEditorKit.pasteAction));
		popupMenu.add(pasteItem);
	}
	
	public PandoraTextPane() {
		super();

		// Create and fill actions array
		actions = new HashMap<Object, Action>();
        Action[] actionsArray = getActions();
        for (int i = 0; i < actionsArray.length; i++) {
            Action a = actionsArray[i];
            actions.put(a.getValue(Action.NAME), a);
        }
        
        // Regexes to use.
        URLRexEx = Pattern.compile("([A-Za-z][A-Za-z0-9+.-]{1,120}:[A-Za-z0-9/](([A-Za-z0-9$_.+!*,;/?:@&~=-])|%[A-Fa-f0-9]{2}){1,333}(#([a-zA-Z0-9][a-zA-Z0-9$_.+!*,;/?:@&~=%-]{0,1000}))?)");
        
        
        // Setup some UI features
		createPoupuMenu();
		addMouseListener(this);
		/*  These lines are for later.  */
        setContentType("text/html");
		setEditorKit(new PandoraHTMLEditorKit());
	}
	
	public void setEditable(boolean b) {
		super.setEditable(b);
		if(null != cutItem)
			cutItem.setEnabled(b);
		if(null != pasteItem)
			pasteItem.setEnabled(b);
	}

	@Override
	public void mouseClicked(MouseEvent e) {

		if(e.getButton() == MouseEvent.BUTTON3){
			popupMenu.show(e.getComponent(), e.getX(), e.getY());
		}
	}

	@Override
	public void mouseEntered(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mouseExited(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mousePressed(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mouseReleased(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}
	
	public void addHyperlink(String url, String text, Style style) {
		  try {
		    // First, setup the href attribute for <A> tag.
		    SimpleAttributeSet hrefAttr = new SimpleAttributeSet();
		    hrefAttr.addAttribute(HTML.Attribute.HREF, url);

		    // Second, setup the <A> tag
		    SimpleAttributeSet attrs = new SimpleAttributeSet();
		    attrs.addAttributes(style);
		    attrs.addAttribute(HTML.Tag.A, hrefAttr);

		    // Add the text along with its attributes.
		    getStyledDocument().insertString(getStyledDocument().getLength(), text, attrs);
		  }
		  catch (BadLocationException e) {
			//TODO: Something useful here
		    e.printStackTrace(System.err);
		  }        
		}
	
	public Style getDefaultStyle() {
		return getStyle("regular");
	}
	
	public void addRawText(String textToWrite) {
		addRawTextWithStyle(textToWrite, getDefaultStyle());
	}
	
	public void addNewline() {
		addRawText("\n");
	}
	
	public void addTextHypertextReplace(String textToWrite, Style style) {
		Matcher matcher = URLRexEx.matcher(textToWrite);
		int start = 0;
		while(matcher.find()){
			addRawTextWithStyle(textToWrite.substring(start, matcher.start()), style);
			addHyperlink(textToWrite.substring(matcher.start(), matcher.end()), textToWrite.substring(matcher.start(), matcher.end()), style);
			start = matcher.end();
		}
		addRawTextWithStyle(textToWrite.substring(start), style);
	}

	public void addRawTextWithStyle(String textToWrite, Style curStyle) {
		StyledDocument doc = getStyledDocument();
		try {
			doc.insertString(doc.getLength(), textToWrite, curStyle);
		} catch (BadLocationException e) {
			// This (should be) actually impossible.
			e.printStackTrace();
		}
	}
	
	public void addStyledText(String textToWrite, Style curStyle) {
		addTextHypertextReplace(textToWrite, curStyle);
	}

	public void addStyledTextLine(String textToWrite, Style curStyle) {
		addTextHypertextReplace(textToWrite, curStyle);
		addNewline();
	}

}
